"""
日志基类

"""
import logging
import os
import re
import time
from datetime import datetime
from functools import wraps
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler

from flask import current_app, g

from components.base_exception import APIException
from components.mysql.connector import db

from dotenv import load_dotenv

load_dotenv('env.ini', encoding='utf-8')


class CustomTimedRotatingFileHandler(TimedRotatingFileHandler):
    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False,
                 atTime=None):
        TimedRotatingFileHandler.__init__(self, filename, when, interval, backupCount, encoding, delay, utc, atTime)
        self.suffix = "%Y-%m-%d"
        self.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}$")

    def doRollover(self):
        if self.stream:
            self.stream.close()
            self.stream = None
        currentTime = int(time.time())
        # dfn = self.baseFilename + "." + time.strftime(self.suffix, time.localtime(currentTime))
        dfn = "/logs" + time.strftime(self.suffix, time.localtime(currentTime)) + '_stdout.log'
        if not os.path.exists(dfn):
            os.rename(self.baseFilename, dfn)
        if self.backupCount > 0:
            for s in self.getFilesToDelete():
                os.remove(s)
        if not self.delay:
            self.stream = self._open()

    def suffix_to_ext(self, suffix):
        return "_stdout.log"


class CustomLogger(logging.Logger):
    def __init__(self, name, level=logging.NOTSET):
        super().__init__(name, level)
        # 创建文件处理器并设置级别为DEBUG
        log_filename = datetime.now().strftime("%Y-%m-%d") + '_stdout.log'
        # debug_handler = RotatingFileHandler("logs/" + log_filename, encoding='utf8', backupCount=5)
        # timed_handler = TimedRotatingFileHandler("logs/" + log_filename, when='midnight', interval=1, backupCount=5)
        timed_handler = RotatingFileHandler('logs/stdout.log', maxBytes=5 * 1024 * 1024, backupCount=3)
        # handler = RotatingFileHandler('logs/stdout.log', maxBytes=5 * 1024 * 1024, backupCount=3)

        # 创建格式器
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

        # 将格式器添加到处理器
        # debug_handler.setFormatter(formatter)
        timed_handler.setFormatter(formatter)
        # 将处理器添加到记录器
        self.addHandler(timed_handler)

    def debug(self, msg, *args, **kwargs):
        super().debug(msg, *args, **kwargs)

    def info(self, msg, *args, **kwargs):
        super().info(msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        super().error(msg, *args, **kwargs)


def log_method_call(func=None, action=None):
    def decorator(inner_func):
        @wraps(inner_func)
        def wrapper(*args, **kwargs):
            import os
            system_name = os.getenv('SYSTEM_NAME')
            worker_id = os.getpid()
            new_dict = {field: value for key, values in g.params.items() for field, value in values.items()}
            params = {**new_dict, **kwargs}
            if args:
                params['pk'] = args[0]
            map_dict = {'10': 'debug', '20': 'info', '40': 'error', '30': 'warning'}
            log_level = map_dict[str(current_app.logger.getEffectiveLevel())]
            import traceback
            try:
                result = inner_func(*args, **kwargs)
                if db.sql_log:
                    sql = db.sql_log
                else:
                    sql = []
            except Exception as e:
                sql = []
                result = {}
                if isinstance(e, APIException):
                    result['message'] = f'{e.message}, {e.data if e.data else ""}'
                    result['code'] = e.code
                    result['data'] = ''
                else:
                    err = traceback.format_exc()
                    print(err)
                    if err:
                        res = [f'RequestRemoteIp: {g.remote_addr}, '
                               f'RequestId: {g.request_id}, '
                               f'SystemId: {system_name}, '
                               f'InstanceId:{worker_id}, '
                               f'Action: {action},'
                               f'Method: {inner_func.__name__},'
                               f'Params: {params}, '
                               f'Result: {err}, '
                               f'Sql: {[]}']
                        method = getattr(current_app.logger, log_level)
                        method(*res)
                        result = {"message": "系统错误", "code": 10005, 'data': ''}
            response = result
            if type(result) in [list, dict]:
                result = result
            else:
                result = result.response[0].decode("utf-8")
            res = [f'{datetime.now()}, '
                   f'{log_level}, '
                   f'RequestId: {g.request_id}, '
                   f'SystemId: {system_name}, '
                   f'InstanceId: {worker_id}, '
                   f'Action: {action},'
                   f'Method: {inner_func.__name__}, '
                   f'Params: {params}, '
                   f'Result: {result}, '
                   f'Sql: {sql}']
            method = getattr(current_app.logger, log_level)
            method(*res)
            return response

        return wrapper

    if func is None:
        return decorator
    else:
        return decorator(func)
